<template>
  <div>
    <el-dialog
      class="nodeImportDialog"
      :title="$t('import.title')"
      v-model="dialogVisible"
      width="350px"
    >
      <el-upload
        ref="uploadRef"
        action="x"
        :accept="supportFileStr"
        :file-list="fileList"
        :auto-upload="false"
        :multiple="false"
        :on-change="onChange"
        :on-remove="onRemove"
        :limit="1"
        :on-exceed="onExceed"
      >
        <template #trigger>
          <el-button size="small" type="primary">{{
            $t('import.selectFile')
          }}</el-button>
        </template>
        <template #tip>
          <div class="el-upload__tip">
            {{ $t('import.support') }}{{ supportFileStr }}{{ $t('import.file') }}
          </div>
        </template>
      </el-upload>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancel">{{ $t('dialog.cancel') }}</el-button>
          <el-button type="primary" @click="confirm">{{
            $t('dialog.confirm')
          }}</el-button>
        </span>
      </template>
    </el-dialog>
    <el-dialog
      class="xmindCanvasSelectDialog"
      :title="$t('import.xmindCanvasSelectDialogTitle')"
      v-model="xmindCanvasSelectDialogVisible"
      width="300px"
      :show-close="false"
    >
      <el-radio-group v-model="selectCanvas" class="canvasList">
        <el-radio
          v-for="(item, index) in canvasList"
          :key="index"
          :value="index"
          >{{ item.title }}</el-radio
        >
      </el-radio-group>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="confirmSelect">{{
            $t('dialog.confirm')
          }}</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { ElMessage } from 'element-plus'
import { useMainStore } from '@/stores'
import { useEventBus } from '@/hooks'

// 动态导入解析模块以避免循环依赖
let xmind = null
let markdown = null

// 异步加载解析模块
const loadParsers = async () => {
  if (!xmind) {
    const xmindModule = await import('simple-mind-map/src/parse/xmind.js')
    xmind = xmindModule.default || xmindModule
  }
  if (!markdown) {
    const markdownModule = await import('simple-mind-map/src/parse/markdown.js')
    markdown = markdownModule.default || markdownModule
  }
}

// 组合式API设置
const { t } = useI18n()
const route = useRoute()
const store = useMainStore()
const { $on, $off, $emit, $once } = useEventBus()

// 响应式数据
const dialogVisible = ref(false)
const fileList = ref([])
const selectPromiseResolve = ref(null)
const xmindCanvasSelectDialogVisible = ref(false)
const selectCanvas = ref('')
const canvasList = ref([])
const mdStr = ref('')

// 模板引用
const uploadRef = ref(null)

// 计算属性
const supportFileStr = computed(() => {
  return '.xmind'
})

// 监听器
watch(dialogVisible, (val, oldVal) => {
  if (!val && oldVal) {
    fileList.value = []
  }
})

// 生命周期钩子
onMounted(() => {
  $on('showImport', handleShowImport)
  $on('handle_file_url', handleFileURL)
  $on('importFile', handleImportFile)
})

onBeforeUnmount(() => {
  $off('showImport', handleShowImport)
  $off('handle_file_url', handleFileURL)
  $off('importFile', handleImportFile)
})

// 方法
const handleShowImport = () => {
  dialogVisible.value = true
}

const getRegexp = () => {
  return new RegExp(`\.(smm|json|xmind|md)$`)
}

// 检查url中是否操作需要打开的文件
const handleFileURL = async () => {
  try {
    const fileURL = route.query.fileURL
    if (!fileURL) return
    const macth = getRegexp().exec(fileURL)
    if (!macth) {
      return
    }
    const type = macth[1]
    const res = await fetch(fileURL)
    const file = await res.blob()
    const data = {
      raw: file
    }
    if (type === 'smm' || type === 'json') {
      handleSmm(data)
    } else if (type === 'xmind') {
      handleXmind(data)
    } else if (type === 'md') {
      handleMd(data)
    }
  } catch (error) {
    console.log(error)
  }
}

// 文件选择
const onChange = (file) => {
  if (!getRegexp().test(file.name)) {
    ElMessage.error(
      t('import.pleaseSelect') +
        supportFileStr.value +
        t('import.file')
    )
    fileList.value = []
  } else {
    fileList.value.push(file)
  }
}

// 移除文件
const onRemove = (file, fileListParam) => {
  fileList.value = fileListParam
}

// 数量超出限制
const onExceed = () => {
  ElMessage.error(t('import.maxFileNum'))
}

// 取消
const cancel = () => {
  dialogVisible.value = false
}

// 确定
const confirm = () => {
  if (fileList.value.length <= 0) {
    return ElMessage.error(t('import.notSelectTip'))
  }
  store.setIsHandleLocalFile(false)
  let file = fileList.value[0]
  if (/\.(smm|json)$/.test(file.name)) {
    handleSmm(file)
  } else if (/\.xmind$/.test(file.name)) {
    handleXmind(file)
  } else if (/\.md$/.test(file.name)) {
    handleMd(file)
  }
  cancel()
  store.setActiveSidebar(null)
}

// 处理.smm文件
const handleSmm = (file) => {
  let fileReader = new FileReader()
  fileReader.readAsText(file.raw)
  fileReader.onload = evt => {
    try {
      let data = JSON.parse(evt.target.result)
      if (typeof data !== 'object') {
        throw new Error(t('import.fileContentError'))
      }
      $emit('setData', data)
      ElMessage.success(t('import.importSuccess'))
    } catch (error) {
      console.log(error)
      ElMessage.error(t('import.fileParsingFailed'))
    }
  }
}

// 处理.xmind文件
const handleXmind = async (file) => {
  try {
    await loadParsers()
    let data = await xmind.parseXmindFile(file.raw, content => {
      showSelectXmindCanvasDialog(content)
      return new Promise(resolve => {
        selectPromiseResolve.value = resolve
      })
    })
    $emit('setData', data)
    ElMessage.success(t('import.importSuccess'))
  } catch (error) {
    console.log(error)
    ElMessage.error(t('import.fileParsingFailed'))
  }
}

// 显示xmind文件的多个画布选择弹窗
const showSelectXmindCanvasDialog = (content) => {
  canvasList.value = content
  selectCanvas.value = 0
  xmindCanvasSelectDialogVisible.value = true
}

// 确认导入指定的画布
const confirmSelect = () => {
  selectPromiseResolve.value(canvasList.value[selectCanvas.value])
  xmindCanvasSelectDialogVisible.value = false
  canvasList.value = []
  selectCanvas.value = 0
}

// 处理markdown文件
const handleMd = async (file) => {
  let fileReader = new FileReader()
  fileReader.readAsText(file.raw)
  fileReader.onload = async evt => {
    try {
      await loadParsers()
      let data = markdown.transformMarkdownTo(evt.target.result)
      $emit('setData', data)
      ElMessage.success(t('import.importSuccess'))
    } catch (error) {
      console.log(error)
      ElMessage.error(t('import.fileParsingFailed'))
    }
  }
}

// 导入指定文件
const handleImportFile = (file) => {
  onChange({
    raw: file,
    name: file.name
  })
  if (fileList.value.length <= 0) return
  confirm()
}
</script>

<style lang="less" scoped>
.nodeImportDialog {
}

.canvasList {
  display: flex;
  flex-direction: column;

  :deep(.el-radio) {
    margin-bottom: 12px;

    &:last-of-type {
      margin-bottom: 0;
    }
  }
}
</style>
